package com.tarena.luban.worker.server.infrastructure.repo.impl;


import com.tarena.luban.worker.server.dao.api.WorkerDAO;
import com.tarena.luban.worker.server.domain.bo.WorkerBO;
import com.tarena.luban.worker.server.domain.repository.WorkerRepository;
import com.tarena.luban.worker.server.infrastructure.converter.WorkerConverter;
import com.tarena.tp.luban.worker.po.Worker;
import com.tarena.tp.luban.worker.server.common.enums.AccountStatusEnum;
import com.tarena.tp.luban.worker.server.common.enums.AuditStatusEnum;
import com.tarena.tp.luban.worker.server.common.enums.StatusEnum;
import com.tarena.tp.luban.worker.server.dto.param.WorkerCreateParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Repository
@Slf4j
public class WorkerRepoImpl implements WorkerRepository {

    @Autowired(required = false)
    private WorkerDAO workerDAO;
    @Autowired
    private WorkerConverter workerConverter;
    // 必做缓存 按照写流程 做缓存 数据库先写(update delete)
    // 缓存在删
    @Override
    public void delete(Long userId) {
        //delete from worker where user_id=#{userId};
        workerDAO.delete(userId);
        String workerKey = "luban:worker:detail:" + userId;
        redisTemplate.delete(workerKey);
    }
    // 写数据库的同时 写缓存,可做 可不做
    // 缓存写流程 主要考虑的是数据一致性

    @Override
    public Long saveWorker(WorkerCreateParam workerCreateParam) {
        //想办法在仓储层 将入参 解析 转化成do
        Worker worker = workerConverter.param2po(workerCreateParam);
        log.info("当前新增入驻师傅,师傅id:{}" , worker.getId());
        //insert into worker(字段们) values(#(对象属性))
        //mybatis可以设置 自动回填自增的id 通过映射文件xml配置
        workerDAO.save(worker);
        log.info("师傅入驻完成,师傅id:{}" , worker.getId());
        return worker.getId();
    }

    /**
     * 缓存策略 cashe-aside 读流程
     * 1. 想办法 读缓存
     * 2. 判断缓存命中
     * 2.1 有 直接返回
     * 2.2 没有 读数据dao,转化存储到缓存,返回数据库数据
     * 一致性怎么保证 cache-aside 写流程
     * 数据发生变动时(update delete),先改数据库 再删缓存
     * @param userId
     * @return
     */
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public WorkerBO detail(Long userId) {
        String workerKey = "luban:worker:detail:" + userId;
        // 缓存是否命中
        Boolean hasWorker = redisTemplate.hasKey(workerKey);
        // string操作对象
        ValueOperations opsForValue = redisTemplate.opsForValue();
        WorkerBO workerBO = null;
        if (hasWorker) {
            //命中
            workerBO = (WorkerBO) opsForValue.get(workerKey);
        }else {
            Worker worker = workerDAO.selectWorkerByUserId(userId);
            //workerBO
            workerBO = workerConverter.po2bo(worker);
            //存放到缓存 选择 超时时长24小时 防止缓存超时导致雪崩 随机5小时
            opsForValue.set(
                    workerKey,
                    workerBO,
                    60l*06*24+new Random().nextInt(60*60*5),
                    TimeUnit.SECONDS);
        }
        return workerBO;
    }

    //入驻师傅 param
    /*private Worker param2do(WorkerCreateParam workerCreateParam) {
        //判断参数是否为空
        Worker worker = new Worker();
        if (workerCreateParam == null) {
            return worker;
        }
        //realName phone userId 把能转化的 名称相同
        BeanUtils.copyProperties(workerCreateParam,worker);
        //通用6个字段 没有填补 手动填
        worker.setGmtCreate(System.currentTimeMillis());
        worker.setGmtModified(worker.getGmtCreate());
        worker.setCreateUserId(100L);
        worker.setCreateUserName("mock");
        worker.setModifiedUserId(100L);
        worker.setModifiedUserName("mock");
        //三个状态 没有填补 手动填
        //1. 师傅 启用 禁用状态 1启用 0禁用 默认启用
        worker.setStatus(StatusEnum.NORMAL.getValue());
        //2. 审核状态 四个值 (驳回0,通过1,未审核2,未入驻3 表格没有未入驻) 默认未审核
        worker.setAuditStatus(AuditStatusEnum.UNAUDITED.getValue());
        //3. 认证状态(0 未认证 1 已认证) 平台账号有没有创建 默认未认证
        worker.setCertStatus(AccountStatusEnum.DISABLE.getValue());
        return worker;
    }*/
}
